﻿#pragma once
#include <functional>

template<class T>
class SmartPtr {
public:
	SmartPtr(T* ptr)
		:_ptr(ptr) {
	}

	~SmartPtr() {
		delete _ptr;
		cout << "~SmartPtr() -> " << _ptr << endl;
	}

	T& operator*() { return *_ptr; }
	T* operator->() { return _ptr; }

private:
	T* _ptr;
};



namespace bit {
	//C++98两种关于智能指针的拷贝和赋值解决方式
	//C++98库实现方式
	//方式一：管理权限转移导致被拷贝的对象置空
	template<class T>
	class auto_ptr {
	public:
		auto_ptr(T* ptr)
			:_ptr(ptr) {
		}

		~auto_ptr() {
			if (_ptr) {
				delete _ptr;
				cout << "delete->" << _ptr << endl;
				_ptr = nullptr;
			}
		}

		//管理权转移 ap2(ap1)
		auto_ptr(auto_ptr<T>& ap)
			:_ptr(ap._ptr) {
			ap._ptr = nullptr;
		}

		T& operator*() { return *_ptr; }
		T* operator->() { return _ptr; }

	private:
		T* _ptr;
	};

	//C++11不允许智能指针拷贝，所以C++98出现方式二：
	template<class T>
	class unique_ptr {
	public:
		unique_ptr(T* ptr)
			:_ptr(ptr) {
		}

		~unique_ptr() {
			delete _ptr;
			cout << "delete->" << _ptr << endl;
		}

		T& operator*() { return *_ptr; }
		T* operator->() { return _ptr; }

		//C++11
		unique_ptr(const unique_ptr<T>& up) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>& up) = delete;

		////C++98方法一：只声明不实现，不让编译器自动生成。
		//unique_ptr(const unique_ptr<T>& up);
		////但这样可能导致别人在类外面实现
		//template <class T>
		//bit::unique_ptr<T>::unique_ptr(const bit::unique_ptr<T>& up) {}
	//private:
	//	//C++98方法二：声明为私有
	//	unique_ptr(const unique_ptr<T>& up);
	//	unique_ptr<T>& operator=(const unique_ptr<T>& up);
	private:
		T* _ptr;
	};

	////可以拷贝版本
	//template<class T>
	//class shared_ptr {
	//public:
	//	shared_ptr(T* ptr = nullptr)
	//		:_ptr(ptr)
	//		, _pcount(new int(1)) {
	//		//构造时开辟存计数的空间，且将计数置为1
	//	}

	//	//~shared_ptr() {
	//	//	if (--(*_pcount) == 0) {
	//	//		delete _ptr;
	//	//		delete _pcount;
	//	//		cout << "delete->" << _ptr << endl;
	//	//	}
	//	//}
	//	//shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
	//	//	//sp赋值给this，this指向的计数(*_pcount)无论如何都要--
	//	//	//不能自己给自己赋值。不仅指相同对象，管理同一资源的不同对象也不可以
	//	//	//否则可能出现--(*_pcount) == 0导致自己被释放
	//	//	if (_ptr != sp._ptr) {
	//	//		if (--(*_pcount) == 0) {
	//	//			delete _ptr;
	//	//			delete _pcount;
	//	//		}
	//	//		_ptr = sp._ptr;
	//	//		_pcount = sp._pcount;
	//	//		++(*_pcount);
	//	//	}
	//	//	return *this;
	//	//}

	//	//复用版本
	//	void release() {
	//		if (--(*_pcount) == 0) {
	//			delete _ptr;
	//			delete _pcount;
	//			//cout << "delete->" << _ptr << endl;
	//		}
	//	}
	//	~shared_ptr() { release(); }
	//	shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
	//		if (_ptr != sp._ptr) {
	//			release();
	//			_ptr = sp._ptr;
	//			_pcount = sp._pcount;
	//			++(*_pcount);
	//		}
	//		return *this;
	//	}

	//	shared_ptr(const shared_ptr<T>& sp)
	//		:_ptr(sp._ptr)
	//		, _pcount(sp._pcount) {
	//		++(*_pcount);
	//	}

	//	T& operator*() { return *_ptr; }
	//	T* operator->() { return _ptr; }
	//	int use_count() const { return *_pcount; }
	//	T* get() const { return _ptr; }
	//private:
	//	T* _ptr;
	//	//int _count;//不可以，智能指针拷贝后两个对象的_count不同步
	//	//static int _count;//不可以，如果两个智能指针管理两个资源，_count的统计就乱了
	//	int* _pcount;//去堆开辟空间存计数
	//};

	//增加定制删除器
	template<class T>
	class shared_ptr {
	public:
		shared_ptr(T* ptr = nullptr)
			:_ptr(ptr)
			, _pcount(new int(1)) {
			//构造时开辟存计数的空间，且将计数置为1
		}

		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _del(del) {
		}
		//function<void(T*)> _del;
		//参数 D 的本质：它是一个"释放资源的方式"，可以处理单个对象或多个对象（比如数组的 delete[]）
		//这个释放方式可以是：仿函数、Lambda 表达式、普通函数指针、其他任何可调用实体(总之是个可调用对象)
		//function 的作用：作为通用的包装器，统一存储这些不同类型的可调用对象

		//复用版本
		void release() {
			if (--(*_pcount) == 0) {
				//仿函数和lambda都是可调用对象
				_del(_ptr);
				delete _pcount;
				//cout << "delete->" << _ptr << endl;
			}
		}
		~shared_ptr() { release(); }
		shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
			if (_ptr != sp._ptr) {
				release();
				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
			}
			return *this;
		}

		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount) {
			++(*_pcount);
		}

		T& operator*() { return *_ptr; }
		T* operator->() { return _ptr; }
		int use_count() const { return *_pcount; }
		T* get() const { return _ptr; }
	private:
		T* _ptr;
		int* _pcount;//去堆开辟空间存计数
		//D _del;//不可行，D是构造函数的模板参数，不是整个类的
		function<void(T*)> _del = [](T* ptr) {delete ptr; };
		//给缺省值的原因：如果使用这个智能指针管理资源，且该资源没有传删除器时调用的是默认构造函数。
		//如果不初始化_del，那么析构时_del为空就报错
	};

	template<class T>
	class weak_ptr {
	public:
		//当执行 new ListNode 时：先分配内存。
		//然后调用 ListNode 的构造函数（隐式生成的默认构造函数）。
		//ListNode 的默认构造函数会调用 next 和 prev 的默认构造函数（因为它们是成员变量）。
		//如果 weak_ptr 没有默认构造函数，ListNode 的默认构造会失败。
		weak_ptr()
			:_ptr(nullptr) {
		}

		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get()) {
		}

		weak_ptr<T>& operator=(const shared_ptr<T>& sp) {
			_ptr = sp.get();
			return *this;
		}

		T& operator*() { return *_ptr; }
		T* operator->() { return _ptr; }
	private:
		T* _ptr;
	};
}
